﻿using Conqueror.API;
using Conqueror.WP.Utility;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace Conqueror.WP.ViewModel.Games
{
    public class GameViewModel : ViewModel
    {
        private string mapName;
        private string mapImage;
        private ObservableCollection<GamePlayerViewModel> players;
        private TimeSpan time;
        private Brush currentPlayerBrush;
        private string gameMode;
        private string reinforcements;
        private string spoils;

        public string MapName
        {
            get { return mapName; }
            set
            {
                if (mapName != value)
                {
                    mapName = value;
                    Notify("MapName");
                }
            }
        }

        public string MapImage
        {
            get { return mapImage; }
            set
            {
                if (mapImage != value)
                {
                    mapImage = value;
                    Notify("MapImage");
                }
            }
        }

        public ObservableCollection<GamePlayerViewModel> Players
        {
            get { return players; }
            set
            {
                if (players != value)
                {
                    players = value;
                    Notify("Players");
                }
            }
        }

        public TimeSpan Time
        {
            get { return time; }
            set
            {
                if (time != value)
                {
                    time = value;
                    Notify("Time");
                    Notify("TimeString");
                }
            }
        }

        public string TimeString
        {
            get { return time.ToString(); }
        }

        public Brush CurrentPlayerBrush
        {
            get { return currentPlayerBrush; }
        }

        public string GameMode
        {
            get { return gameMode; }
        }

        public string Reinforcements
        {
            get { return reinforcements; }
        }

        public string Spoils
        {
            get { return spoils; }
        }

        public GamePlayerState State
        {
            get;
            set;
        }

        public string GameNumber
        {
            get;
            set;
        }

        private Visibility privateGame;
        public Visibility PrivateGame { get { return privateGame; } }

        public GameViewModel(Conqueror.API.Game game)
        {
            mapName = game.Map;

            if (!TimeSpan.TryParse(game.TimeRemaining, out time))
            {
                time = new TimeSpan(0, 0, 0);
            }

            players = new ObservableCollection<GamePlayerViewModel>();
            IEnumerable<API.GamePlayer> gamePlayers = game.Players.Players.OrderByDescending
                    (player => player.State == API.GamePlayerState.Ready ||
                    player.State == API.GamePlayerState.Won ||
                    player.State == API.GamePlayerState.Playing);
            foreach(var p in gamePlayers)
            {
                players.Add(new GamePlayerViewModel(p));
            }

            FindGame(mapName);
            FindPlayerState(User.Username, gamePlayers);

            if (game.Private == API.Query.Yes)
                privateGame = Visibility.Visible;
            else privateGame = Visibility.Collapsed;

            switch(game.Type)
            {
                case API.GameType.Standard:
                    gameMode = "Standard Game"; break;
                case API.GameType.Doubles:
                    gameMode = "Double Game"; break;
                case API.GameType.Triples:
                    gameMode = "Triples Game"; break;
                case API.GameType.Quadruples:
                    gameMode = "Quadruples Game"; break;
                case API.GameType.Assassin:
                    gameMode = "Assassins Game"; break;
                case API.GameType.Terminator:
                    gameMode = "Terminator Game"; break;
                case API.GameType.Polymorphic:
                    gameMode = "Polymorphic Game"; break;
                default:
                    gameMode = "Unknown Game"; break;
            }

            switch(game.Fortification)
            {
                case API.Fortifications.Adjacent:
                    reinforcements = "Adjacent Reinforcements"; break;
                case API.Fortifications.Chained:
                    reinforcements = "Chained Reinforcements"; break;
                case API.Fortifications.Unlimited:
                    reinforcements = "Unlimited Reinforcements"; break;
                case Fortifications.Parachute:
                    reinforcements = "Parachute Reinforcements"; break;
                default:
                    reinforcements = "Unknown Reinforcements"; break;
            }

            switch(game.BonusCards)
            {
                case API.Spoils.NoSpoils:
                    spoils = "No Spoils"; break;
                case API.Spoils.FlatRate:
                    spoils = "Flat Rate Spoils"; break;
                case API.Spoils.Escalating:
                    spoils = "Escalating Spoils"; break;
                case API.Spoils.Nuclear:
                    spoils = "Nuclear Spoils"; break;
            }

            GameNumber = game.GameNumber;
        }

        private void FindPlayerState(string p, IEnumerable<API.GamePlayer> players)
        {
            currentPlayerBrush = PlayerColors.GetBrush(GamePlayerState.Unknown);
            foreach(var player in players)
            {
                if (player.Name.ToLower().Equals(p.ToLower()))
                {
                    currentPlayerBrush = PlayerColors.GetBrush(player.State);
                    State = player.State;
                    Notify("CurrentPlayerBrush");
                    return;
                }
            }
        }

        private async void FindGame(string mapName)
        {
            API.Map map = (await API.Map.GetMapAsync(mapName)).First();
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                MapImage = map.LargeImage;
            });
        }
    }
}
